import {GenderEnum} from "../../common/common.js";

class FilterCategory {
    /**
     *
     * @param {String} key
     * @param {String} name
     * @param {String} type
     * @param {Array<FilterOption>} options 如果 type == FilterCategoryType.options，则必填，不能为空数组
     * @param {Array<FilterCategory>} subCategories 如果 type == FilterCategoryType.subCategories，则必填，不能为空数组
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({key, name, type = FilterCategoryType.options, options = [], subCategories = []} = {}) {
        if (typeof key !== 'string') throw new Error('FilterCategory: The "key" field must be a string and is required.');
        if (typeof name !== 'string') throw new Error('FilterCategory: The "name" field must be a string and is required.');
        if (typeof type !== 'string') throw new Error('FilterCategory: The "type" field must be a string.');
        if (!Array.isArray(options)) throw new Error('FilterCategory: The "options" field must be an array.');
        if (!Array.isArray(subCategories)) throw new Error('FilterCategory: The "subCategories" field must be an array.');

        if ((type === FilterCategoryType.all || type === FilterCategoryType.options) && options.length === 0) {
            throw new Error('FilterCategory: The "options" field must not be an empty array when type is "options".');
        }

        if ((type === FilterCategoryType.all || type === FilterCategoryType.subCategories) && subCategories.length === 0) {
            throw new Error('FilterCategory: The "subCategories" field must not be an empty array when type is "subCategories".');
        }

        this.key = key;
        this.name = name;
        this.type = type;
        this.options = options;
        this.subCategories = subCategories;
    }

    /**
     *
     * @param {Boolean} selectLast 选择最后一个
     * @return {FilterParameter}
     */
    defaultFilterParameter(selectLast = false) {
        if (this.type === FilterCategoryType.subCategories) {

        } else {
            return new FilterParameter({
                key: this.key,
                type: this.type,
                optionsValue: this.options[selectLast ? this.options.length - 1 : 0].value
            })
        }

        return new FilterParameter({
            key: this.key,
            type: this.type,
            subCategoriesValue: this.type === FilterCategoryType.all || this.type === FilterCategoryType.subCategories ?
                this.subCategories[selectLast ? this.subCategories.length - 1 : 0].defaultFilterParameter(selectLast)
                : null,
            optionsValue: this.type === FilterCategoryType.all || this.type === FilterCategoryType.options ? this.options[selectLast ? this.options.length - 1 : 0].value : null
        })
    }
}

class FilterOption {
    /**
     *
     * @param {String} key
     * @param {String} name
     * @param {String} value
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({key, name, value} = {}) {
        if (typeof key !== 'string') throw new Error('FilterOption: The "key" field must be a string and is required.');
        if (typeof name !== 'string') throw new Error('FilterOption: The "name" field must be a string and is required.');
        if (typeof value !== 'string') throw new Error('FilterOption: The "value" field must be a string and is required.');

        this.key = key;
        this.name = name;
        this.value = value;
    }
}

class FilterParameter {
    /**
     *
     * @param {String} key
     * @param {String} type
     * @param {FilterParameter|null} subCategoriesValue 如果 type == FilterCategoryType.subCategories，则必填，不能为空
     * @param {String|null} optionsValue 如果 type == FilterCategoryType.options，则必填，不能为空
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({key, type, subCategoriesValue, optionsValue} = {}) {
        if (typeof key !== 'string') throw new Error('FilterParameter: The "key" field must be a string and is required.');
        if (typeof type !== 'string') throw new Error('FilterParameter: The "type" field must be a string and is required.');

        if ((type === FilterCategoryType.all || type === FilterCategoryType.subCategories) && !(subCategoriesValue instanceof FilterParameter)) {
            throw new Error('FilterParameter: The "subCategoriesValue" field must be an instance of FilterParameter when type is "subCategories" and is required.');
        }

        if ((type === FilterCategoryType.all || type === FilterCategoryType.options) && (typeof optionsValue !== 'string')) {
            throw new Error('FilterParameter: The "optionsValue" field must be a non-null string when type is "options" and is required.');
        }

        this.key = key;
        this.type = type;
        this.subCategoriesValue = subCategoriesValue;
        this.optionsValue = optionsValue;
    }
}

const FilterCategoryType = {
    options: "options",
    subCategories: "subCategories",
    all: "all"
};


/**
 * 表示发现的书籍，包含详细信息。
 */
class DiscoverBook {
    /**
     *
     * @param {String} name 书的名称。必填。
     * @param {String|null} author 书的作者。必填。
     * @param {String|null} intro 书的简介。
     * @param {String|null} coverUrl 书的封面URL。
     * @param {String|null} type 书的类型。
     * @param {String|null} status 书的状态。
     * @param {BookLink|null} link 书籍链接，如果有，则可以直接打开书籍。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({name, author = null, intro = null, coverUrl = null, type = null, status = null, link = null} = {}) {
        if (typeof name !== 'string') throw new Error('DiscoverBook: The "name" field must be a string and is required.');
        if (author && typeof author !== 'string') throw new Error('DiscoverBook: The "author" field must be a string.');
        if (intro && typeof intro !== 'string') throw new Error('DiscoverBook: The "intro" field must be a string.');
        if (coverUrl && typeof coverUrl !== 'string') throw new Error('DiscoverBook: The "coverUrl" field must be a string.');
        if (type && typeof type !== 'string') throw new Error('DiscoverBook: The "type" field must be a string.');
        if (status && typeof status !== 'string') throw new Error('DiscoverBook: The "status" field must be a string.');
        if (link && !link instanceof BookLink) throw new Error('DiscoverBook: The "link" field must be a BookLink.');

        this.name = name;
        this.author = author;
        this.intro = intro;
        this.coverUrl = coverUrl;
        this.type = type;
        this.status = status;
        this.link = link;
    }
}

/**
 * 表示书籍链接信息。
 */
class BookLink {
    /**
     *
     * @param {String} subscriptionId 订阅ID。必填。
     * @param {String} sourceId 来源ID。必填。
     * @param {String} bookPath 书籍路径。必填。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({subscriptionId, sourceId, bookPath} = {}) {
        if (typeof subscriptionId !== 'string') throw new Error('BookDetailsPageQuery: The "subscriptionId" field must be a string and is required.');
        if (typeof sourceId !== 'string') throw new Error('BookDetailsPageQuery: The "sourceId" field must be a string and is required.');
        if (typeof bookPath !== 'string') throw new Error('BookDetailsPageQuery: The "bookPath" field must be a string and is required.');

        this.subscriptionId = subscriptionId;
        this.sourceId = sourceId;
        this.bookPath = bookPath;
    }
}


/**
 * 表示分页结果，包含分页详细信息和列表数据。
 */
class PageResult {
    /**
     *
     * @param {Number} pageNum 当前页码。必填。
     * @param {Number} pages 总页数。必填。
     * @param {Array<?>} list 数据列表。必填。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({pageNum, pages, list} = {}) {
        if (typeof pageNum !== 'number') throw new Error('PageResult: The "pageNum" field must be a number and is required.');
        if (typeof pages !== 'number') throw new Error('PageResult: The "pages" field must be a number and is required.');
        if (!Array.isArray(list)) throw new Error('PageResult: The "list" field must be an array and is required.');

        this.pageNum = pageNum;
        this.pages = pages;
        this.list = list;
    }
}


class DiscoverSource {
    /**
     * @param {String} subscriptionId 订阅id。必填。
     * @param {String} id 编号。必填。
     * @param {String} name 名字。必填。
     * @param {Boolean} active 是否可用。必填。
     * @param {Number} order 在订阅下的排序，越大越靠前，默认为 0
     * @param {String} portalUrl 门户网站。必填。如果分男女，则使用 | 分开，前面为男生频道的portalUrl，后面为女生频道的portalUrl
     * @param {String|null} description 来源描述。
     * @param {PageTurningMode} pageTurningMode 翻页方式。必填。
     * @param {Boolean} enableGenderFilter 是否开启性别过滤。必填。
     * @param {Boolean} enableDiscover 是否开启发现。必填。
     * @param {Boolean} enableHotKeyword 是否开启热搜词条。必填。
     * @throws {Error} Throws an error if required parameters are missing or invalid.
     */
    constructor({
                    subscriptionId,
                    id,
                    name,
                    active,
                    order = 0,
                    portalUrl,
                    description = null,
                    pageTurningMode,
                    enableGenderFilter = false,
                    enableDiscover = false,
                    enableHotKeyword = false,
                } = {}) {
        if (typeof subscriptionId !== 'string') throw new Error('DiscoverSource: The "subscriptionId" field must be a string and is required.');
        if (typeof id !== 'string') throw new Error('DiscoverSource: The "id" field must be a string and is required.');
        if (typeof name !== 'string') throw new Error('DiscoverSource: The "name" field must be a string and is required.');
        if (typeof active !== 'boolean') throw new Error('DiscoverSource: The "active" field must be a boolean and is required.');
        if (typeof order !== 'number') throw new Error('DiscoverSource: The "order" field must be a number.');
        if (typeof portalUrl !== 'string') throw new Error('DiscoverSource: The "portalUrl" field must be a string and is required.');
        if (description && typeof description !== 'string') throw new Error('DiscoverSource: The "description" field must be a string.');
        if (typeof pageTurningMode !== 'string' || (pageTurningMode !== PageTurningMode.scroll && pageTurningMode !== PageTurningMode.pagination)) {
            throw new Error('DiscoverSource: The "pageTurningMode" field must be either "scroll" or "pagination" and is required.');
        }
        if (typeof enableDiscover !== 'boolean') throw new Error('DiscoverSource: The "enableDiscover" field must be a boolean.');
        if (typeof enableHotKeyword !== 'boolean') throw new Error('DiscoverSource: The "enableHotKeyword" field must be a boolean.');
        if (typeof enableGenderFilter !== 'boolean') throw new Error('DiscoverSource: The "enableGenderFilter" field must be a boolean.');
        this.subscriptionId = subscriptionId;
        this.id = id;
        this.name = name;
        this.active = active;
        this.order = order;
        this.portalUrl = portalUrl;
        this.description = description;
        this.pageTurningMode = pageTurningMode;
        this.enableDiscover = enableDiscover;
        this.enableHotKeyword = enableHotKeyword;
        this.enableGenderFilter = enableGenderFilter;
    }

    /**
     *
     * @param {Gender} gender
     * @return {string|null}
     */
    getPortalUrl(gender) {
        const portalUrlArr = this.portalUrl.split('|');
        if (portalUrlArr.length === 0) {
            return null;
        }
        return (gender === GenderEnum.female && portalUrlArr.length > 1 ? portalUrlArr[1] : portalUrlArr[0]).trim();
    }

    // 与订阅json中的结构保持一致，方便Ctrl + c、v
    static createTestDiscoverSource({
                                        id,
                                        name,
                                        active,
                                        order = 0,
                                        portalUrl,
                                        description,
                                        pageTurningMode,
                                        enableGenderFilter,
                                        enableDiscover,
                                        enableHotKeyword,
                                    }) {
        return new DiscoverSource({
            subscriptionId: "test",
            id,
            name,
            active,
            order,
            portalUrl,
            description,
            pageTurningMode,
            enableGenderFilter,
            enableDiscover,
            enableHotKeyword,
        })

    }

}

const PageTurningMode = {
    scroll: "scroll", // 滚动
    pagination: "pagination" // 分页
}

export {
    FilterCategory,
    FilterOption,
    FilterParameter,
    FilterCategoryType,
    DiscoverBook,
    BookLink,
    PageResult,
    DiscoverSource,
}